package czk.concrent.enjoyModelWithNotLock.unsafe.practice;


import lombok.ToString;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * 获取unsafe对象工具类
 * @Author:ChenZhangKun
 * @Date: 2020/12/9 22:41
 */
public class UnsafeUtils {
    /**
     * 定义常量
     */
    private static  Unsafe unsafe;
    /**
     * 私有构造器
     */
    private UnsafeUtils(){}

    /**
     * 获取unsafe
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
        // 拿到域对象
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        // s设置其为公有
        theUnsafe.setAccessible(true);
        // 拿到对象
        if (unsafe==null) {
            synchronized (UnsafeUtils.class) {
                if (unsafe == null) {
                    // 只有一个线程会进入
                    System.out.println(Thread.currentThread().getName()+"进来了");
                    unsafe = (Unsafe) theUnsafe.get(null);
                }
            }
        }
        return unsafe;
    }

    public static void main(String[] args)  {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                // 拿到对象
                Unsafe unsafe = null;
                try {
                    unsafe = UnsafeUtils.getUnsafe();
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                Person person=new Person();
                // 拿到偏移量
                long name = 0;
                long age = 0;
                try {
                    name = unsafe.objectFieldOffset(person.getClass().getDeclaredField("name"));
                    age = unsafe.objectFieldOffset(person.getClass().getDeclaredField("age"));
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
                // cas赋值
                boolean b = unsafe.compareAndSwapObject(person, name, null, "czk");
                boolean b1 = unsafe.compareAndSwapInt(person, age, 0, 26);
                System.out.println(b);
                System.out.println(b1);
                System.out.println(person);
            }).start();
        }
    }
}
@ToString
class Person{
    private String name;
    private int age;
}
